﻿//
//  Copyright (c) 2009,2010 Liang Quan Qing.
//  All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions
//  are met:
//  1. Redistributions of source code must retain the above copyright
//     notice, this list of conditions and the following disclaimer.
//  2. Redistributions in binary form must reproduce the above copyright
//     notice, this list of conditions and the following disclaimer in the
//     documentation and/or other materials provided with the distribution.
//
//  THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
//  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
//  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
//  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
//  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
//  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
//  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
//  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
//  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
//  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
//  SUCH DAMAGE.
//

#ifndef FASTCONV_H_ACD5A7CEBF87BB239E46D76712EC03A1
#define FASTCONV_H_ACD5A7CEBF87BB239E46D76712EC03A1

#include <stddef.h>

#if defined( _MSC_VER )

    #ifdef _NATIVE_WCHAR_T_DEFINED
        typedef wchar_t WChar_t;
    #else
        typedef unsigned short WChar_t;
    #endif
    typedef unsigned int DChar_t;
    #define FASTCONV_WCHAR_T_DEFINED    1

    #ifdef BUILD_FASTCONV_LIB
        #define FCNV_API
    #else
        #define FCNV_API
    #endif

#elif defined( __BORLANDC__ )

    #ifdef  __cplusplus
        typedef wchar_t WChar_t;
    #else
        typedef unsigned short WChar_t;
    #endif
    typedef unsigned int DChar_t;
    #define FASTCONV_WCHAR_T_DEFINED    1

#elif defined( __GNUC__ )

    #if ( defined(__MINGW32__) || defined(__CYGWIN__) )
        typedef wchar_t WChar_t;
        typedef unsigned int DChar_t;
    #else                                           //Linux,FreeBSD,OpenBSD,NetBSD,SunOS ... and so on
        typedef unsigned short WChar_t;
        typedef wchar_t DChar_t;
    #endif
    #define FASTCONV_WCHAR_T_DEFINED    1

#endif

#ifndef FASTCONV_WCHAR_T_DEFINED
    typedef unsigned short WChar_t;
    typedef unsigned int DChar_t;
    #define FASTCONV_WCHAR_T_DEFINED    1
#endif

#ifdef __cplusplus
    extern "C" {
#endif


struct _fcnv_t
{
    size_t          inCount;
    size_t          outCount;
    int             error;
    unsigned int    reserved;
    unsigned int    privdata[32];
};
typedef struct _fcnv_t fcnv_t;

#define FCNV_OK                         0       // succeed
#define FCNV_ERR_NONE                   0       // succeed
#define FCNV_ERR_NOT_SUPPORTED         (-1)     // conversion name not supported
#define FCNV_ERR_NOT_ENOUGH            (-2)     // destination buffer not enough
#define FCNV_ERR_ILLEGAL_CHARS         (-3)     // illegal character in source string sequence
#define FCNV_ERR_CANNOT_CONVERT        (-4)     // cannot convert

int fcnv_Init ( const char* pEncodingName, fcnv_t* pfcnv);
int fcnv_InitW( const WChar_t* pEncodingName, fcnv_t* pfcnv);
int fcnv_InitD( const DChar_t* pEncodingName, fcnv_t* pfcnv);
int fcnv_Setup( fcnv_t*     pfcnv,
                int         boUseDefaultChar,
                const char* pDefaultChar,
                WChar_t     DefaultWChar);

int fcnv_GetMaxCharSize(const fcnv_t* pfcnv);
int fcnv_GetMinCharSize(const fcnv_t* pfcnv);

int fcnv_ToUTF16(   fcnv_t*     pfcnv,
                    const char* srcString,
                    size_t      srcSizeInBytes,
                    WChar_t *   pBuffer,
                    size_t      destSizeInWChars);
int fcnv_FromUTF16( fcnv_t*     pfcnv,
                    const WChar_t* srcString,
                    size_t      srcSizeInWChars,
                    char *      pBuffer,
                    size_t      destSizeInBytes);

int fcnv_ToUnicode( fcnv_t*     pfcnv,
                    const char* srcString,
                    size_t      srcSizeInBytes,
                    WChar_t *   pBuffer,
                    size_t      destSizeInWChars);
int fcnv_FromUnicode( fcnv_t*     pfcnv,
                    const WChar_t* srcString,
                    size_t      srcSizeInWChars,
                    char *      pBuffer,
                    size_t      destSizeInBytes);

int fcnv_ToUTF8(    fcnv_t*     pfcnv,
                    const char* srcString,
                    size_t      srcSizeInBytes,
                    char *      pBuffer,
                    size_t      destSizeInBytes);
int fcnv_FromUTF8(  fcnv_t*     pfcnv,
                    const char* srcString,
                    size_t      srcSizeInBytes,
                    char *      pBuffer,
                    size_t      destSizeInBytes);

int fcnv_ToUTF32(   fcnv_t*     pfcnv,
                    const char* srcString,
                    size_t      srcSizeInBytes,
                    DChar_t *   pBuffer,
                    size_t      destSizeInDChars);
int fcnv_FromUTF32( fcnv_t*     pfcnv,
                    const DChar_t*srcString,
                    size_t      srcSizeInDChars,
                    char *      pBuffer,
                    size_t      destSizeInBytes);

int fcnv_UTF16SwapEndian(WChar_t * pBuffer, size_t sizeInWChars);
int fcnv_UTF32SwapEndian(DChar_t * pBuffer, size_t sizeInDChars);

int fcnv_UnicodeSwapEndian(WChar_t * pBuffer, size_t sizeInWChars);

int fcnv_GetFirstCharLength(const fcnv_t* pfcnv, const char* s);
int fcnv_IsLeadByte(const fcnv_t* pfcnv, const char* s);
typedef int (*fpGetFirstCharLen_t)(const char *s);
typedef int (*fpIsLeadByte_t)(const char *s);
fpGetFirstCharLen_t fcnv_GetFp_GetFirstCharLength(const fcnv_t* pfcnv);
fpIsLeadByte_t fcnv_GetFp_IsLeadByte(const fcnv_t* pfcnv);

int fcnv_CheckUTF8String(const char* string, size_t size);
int fcnv_IsBigEndian(void);
int fcnv_IsLittleEndian(void);
const char* fcnv_GetSystemDefaultCharset(void);

size_t  fcnv_UTF8LengthFromUTF16 (const WChar_t * utf16str);         //in bytes
size_t  fcnv_UTF8LengthFromUTF32 (const DChar_t * utf32str);         //in bytes
size_t  fcnv_UTF16LengthFromUTF8 (const char    * utf8str);          //in WChars
size_t  fcnv_UTF16LengthFromUTF32(const DChar_t * utf32str);         //in WChars
size_t  fcnv_UTF32LengthFromUTF8 (const char    * utf8str);          //in DChars
size_t  fcnv_UTF32LengthFromUTF16(const WChar_t * utf16str);         //in DChars

//char* fcnvStrCpyU16ToU8(char *strDest, const WChar_t *strSrc);
//char* fcnvStrCpyU32ToU8(char *strDest, const DChar_t *strSrc);
//WChar_t* fcnvStrCpyU8ToU16(WChar_t *strDest, const char *strSrc);
//WChar_t* fcnvStrCpyU32ToU16(WChar_t *strDest, const DChar_t *strSrc);
//DChar_t* fcnvStrCpyU8ToU32(WChar_t *strDest, const char *strSrc);
//DChar_t* fcnvStrCpyU16ToU32(WChar_t *strDest, const WChar_t *strSrc);

//char*  fcnvStrCatU16ToU8(char *strDest, const WChar_t *strSrc);
//char*  fcnvStrCatU32ToU8(char *strDest, const DChar_t *strSrc);
//WChar_t*  fcnvStrCatU8ToU16(WChar_t *strDest, const char *strSrc);
//WChar_t*  fcnvStrCatU32ToU16(WChar_t *strDest, const DChar_t *strSrc);
//DChar_t*  fcnvStrCatU8ToU32(WChar_t *strDest, const char *strSrc);
//DChar_t*  fcnvStrCatU16ToU32(WChar_t *strDest, const WChar_t *strSrc);

size_t  wstrlen(const WChar_t *s);
size_t  dstrlen(const DChar_t *s);

// convert a UTF-16 string to UTF-8 string
// if srclen==0, src is a NULL-terminated UTF-16 string.
// if dest==NULL, return size of space need to.
size_t fcnv_UTF16ToUTF8(char * dest, const WChar_t * src, size_t srclen, int * pError);
size_t fcnv_UTF32ToUTF8(char * dest, const DChar_t * src, size_t srclen, int * pError);

#ifdef __cplusplus
    }   //extern "C"
#endif

#endif  //FASTCONV_H_ACD5A7CEBF87BB239E46D76712EC03A1

